/**
 * Project Name:dyrj-admin
 * File Name:SysLogService.java
 * Package Name:com.dyrj.base.system.log.service
 * Date:2017年10月11日下午3:40:23
 * Copyright (c) 2017, zhang.xiangyu@foxmail.com All Rights Reserved.
*/
package com.dyrj.base.system.log.service;

import java.lang.reflect.Method;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.dyrj.constant.SysFrameConst;
import com.dyrj.vo.PageResultMsg;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.dyrj.component.OperateLog;
import com.dyrj.base.system.log.dao.SysLogMapper;
import com.dyrj.base.system.log.model.SysLog;
import com.dyrj.base.system.user.model.SysUser;

/**
 * @Title: SysLogService.java
 * @Description: todo(日志记录服务类)
 * @Author:
 * @Date: 2018/9/5 上午9:59
 * @Version: V1.0
 */
@Log4j2
@Service
public class SysLogService {
	@Resource
	private SysLogMapper sysLogMapper;
	
	public void save(HttpServletRequest request, JoinPoint joinPoint, Throwable e) {
		SysLog sysLog = new SysLog();
		HttpSession session = request.getSession();
		//读取session中的用户    
        SysUser user = (SysUser) session.getAttribute(SysFrameConst.SYSTEM_USER);
        if(user == null && joinPoint.getArgs().length > SysFrameConst.ZERO) {
        	try {
        		user = (SysUser) joinPoint.getArgs()[SysFrameConst.ZERO];
			} catch (Exception e2) {
				user = new SysUser();
	        	BeanUtils.copyProperties(joinPoint.getArgs()[SysFrameConst.ZERO], user);
			}
        }
        //请求的IP    
        String ip = request.getRemoteAddr();  
        
        try {
			// 控制台输出
            log.info("=======================通知开始=======================");
            if(e != null) {
            	log.info("异常代码：{}", e.getClass().getName());
            	log.info("异常信息：{}", e.getMessage());
            	log.info("异常方法：{}.{}()", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName());
            }
            String str_description = getMethodDescription(joinPoint);
            log.info("请求方法：{}.{}()", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName());
            log.info("方法描述：{}", str_description);
            log.info("请求人：{}", user.getAccount());
            log.info("请求IP：{}", ip);
            
            // 数据库日志
            sysLog.setDescription(str_description);
            sysLog.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            sysLog.setRequestIp(ip);    
            sysLog.setOperateUser(user.getAccount());    
            sysLog.setOperateDate(new Date()); 
            
         // 获取用户请求方法的参数并序列化为JSON格式字符串
            String params = "";
            try {
				if (joinPoint.getArgs() != null && joinPoint.getArgs().length > SysFrameConst.ZERO) {
					for (int i = SysFrameConst.ZERO; i < joinPoint.getArgs().length; i++) {
						params += JSON.toJSONString(joinPoint.getArgs()[i]) + ";";
					}
				}
			} catch (Exception e2) {
            	e2.printStackTrace();
			}
			sysLog.setParams(params);
            
			if (e != null) {
				
				// 0: 普通日志；1: 异常日志
				sysLog.setType(SysFrameConst.ONE);
				sysLog.setExceptionCode(e.getClass().getName());    
	            sysLog.setExceptionDetail(e.getMessage());    
	            
	            log.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
			} else {
				sysLog.setType(SysFrameConst.ZERO);
			}
			// 保存数据库
			sysLogMapper.insertSelective(sysLog);
			log.info("=======================通知结束=======================");
		} catch (Exception e1) {
			//记录本地异常日志    
			log.error("==前置通知异常==");    
			log.error("异常信息:{}", e1.getMessage());
			sysLog.setType(SysFrameConst.ONE);
			sysLog.setExceptionCode(e1.getClass().getName());
			sysLog.setExceptionDetail(e1.getMessage());
			sysLogMapper.insertSelective(sysLog);
			e1.printStackTrace();
		}
	}
	
	/**
	 * @Title: getMethodDescription
	 * @Description: todo(获取注解中对方法的描述信息 用于Controller层注解)
	 * @Params: [joinPoint]
	 * @Return: java.lang.String    返回类型
	 * @Author:
	 * @Date: 2018/9/5 上午10:04
	 */
	private String getMethodDescription(JoinPoint joinPoint)  throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class<?> targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class<?>[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					boolean is_same=true;
					for(int k=0;k<arguments.length;k++){
						Class cls_obj = clazzs[k];
						Object arg_obj = arguments[k];
						if(!arg_obj.getClass().getName().equals(cls_obj.getTypeName())){
							is_same = false;
							break;
						}
					}
					if(is_same){
						description = method.getAnnotation(OperateLog.class).value();
						break;
					}
				}
			}
        }

		return description;
    }
	public PageResultMsg table(SysLog record) {
//		SysUser sysUser = (SysUser) SecurityUtils.getSubject().getSession().getAttribute(SysFrameConst.SYSTEM_USER);
//		record.setLoginUser(sysUser.getAccount());
		PageInfo<SysLog> page = PageHelper.startPage(record.getOffset(), record.getLimit()).doSelectPageInfo(() -> sysLogMapper.selectPage(record));
		return new PageResultMsg(SysFrameConst.ResultCode.SUCCESS.CODE, page.getTotal(), page.getList());
	}
}
